#include <pthread.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>

#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <thread>
#include <vector>

using namespace std;

#define NUM 3  // 需要创建一批线程的个数

int g_val = 700;  // 创建一个全局变量作为共享资源

class threadData {
  /* 封装一个类 作为线程的基本信息存储 */
 public:
  threadData(int number) { threadname_ = "Thread_" + to_string(number); }

 public:
  std::string threadname_;
};

void *threadRoutine(void *args) {
  int *arg = static_cast<int *>(args);
  threadData self_data(*arg);
  while (true) {
    // 每个线程都对该全局变量进行访问
    if (g_val > 0) {
      // g_val > 0 时打印对应值并对该g_val进行 -- 操作
      usleep(100);
      printf("I am %s , g_val = %d\n", self_data.threadname_.c_str(), g_val);
      --g_val;
    } else {
      // g_val < 0 时break 退出
      break;
    }
  }
  return nullptr;
}

int main() {
  std::vector<pthread_t> tids;

  for (size_t i = 0; i < NUM; ++i) {
    // 循环创建一批线程
    pthread_t tid;
    pthread_create(&tid, nullptr, threadRoutine, &i);
    tids.push_back(tid);
  }

  for (size_t i = 0; i < tids.size(); ++i) {
    // 循环 join 这批线程
    pthread_join(tids[i], nullptr);
  }
  return 0;
}

// ##################################################

// int g_val = 700;  // 创建一个全局变量作为共享资源

// class threadData {
//   // 封装一个类进行线程基本信息的存储
//  public:
//   threadData(int number) { threadname_ = "Thread_" + to_string(number); }

//  public:
//   std::string threadname_;
// };

// void *threadRoutine(void *args) {
//   int *arg = static_cast<int *>(args);
//   threadData self_data(*arg);
//   while (--g_val > 0) {  // 当
//     /*每个线程都对该全局变量进行访问并打印出对应结果*/
//     usleep(100);
//     printf("I am %s , g_val = %d\n", self_data.threadname_.c_str(), g_val);
//   }
//   return nullptr;
// }

// int main() {
//   std::vector<pthread_t> tids;

//   for (size_t i = 0; i < NUM; ++i) {
//     pthread_t tid;
//     pthread_create(&tid, nullptr, threadRoutine, &i);
//     tids.push_back(tid);
//   }

//   for (size_t i = 0; i < tids.size(); ++i) {
//     pthread_join(tids[i], nullptr);
//   }
//   return 0;
// }

// #########################################################

// #define NUM 3  // 需要创建一批线程的个数

// class threadData {
//  public:
//   threadData(const pthread_t tid) : tid_(tid) {
//     threadname_ = "Thread_" + std::to_string(tid % 1000);
//   }

//  public:
//   pthread_t tid_;
//   std::string threadname_;
// };

// void handler(int signo){
//   cout<<"catch a signal , the signo is "<<signo<<endl;
//   sleep(1);
// }

// void *threadRoutine(void *args) {
//   pthread_t tid = pthread_self();
//   pthread_detach(tid); // 线程自行分离
//   threadData self_data(tid);
//   int cnt = 2;
//   while (cnt--) {
//     printf("I am %s , the tid : %p\n", self_data.threadname_.c_str(),
//            (void *)tid);
//     sleep(1);
//   }
//   // 两秒后为线程发送九号信号
//   pthread_kill(tid,SIGINT);

//   while (true) {
//     printf("I am %s , the tid : %p\n", self_data.threadname_.c_str(),
//            (void *)tid);
//     sleep(1);
//   }
//   return nullptr;
// }

// int main() {
//   std::vector<pthread_t> tids;

//   for (size_t i = 0; i < NUM; ++i) {
//     pthread_t tid;
//     pthread_create(&tid, nullptr, threadRoutine, nullptr);
//     tids.push_back(tid);
//   }

//   signal(SIGINT,handler);

// while(true){
//   cout<<"I am main thread\n"<<endl; // 循环打印
//   sleep(1);
// }
//   return 0;
// }

// // ##################################################

// class threadData {
//  public:
//   threadData(const pthread_t tid) : tid_(tid) {
//     threadname_ = "Thread_" + std::to_string(tid % 1000);
//   }

//  public:
//   pthread_t tid_;
//   std::string threadname_;
// };

// void *threadRoutine(void *args) {
//   pthread_t tid = pthread_self();
//   threadData self_data(tid);
//   while (1) {
//     printf("I am %s , the tid : %p\n", self_data.threadname_.c_str(),
//            (void *)tid);
//     sleep(1);
//   }
//   return nullptr;
// }

// int main() {
//   std::vector<pthread_t> tids;

//   for (size_t i = 0; i < NUM; ++i) {
//     pthread_t tid;
//     pthread_create(&tid, nullptr, threadRoutine, nullptr);
//     tids.push_back(tid);
//   }

//   for (int i = 0; i < NUM; ++i) {
//     // 循环调用 pthread_detach() 来分离所有线程
//     pthread_detach(tids[i]);
//   }

//   for (size_t i = 0; i < tids.size(); ++i) {
//     int n = pthread_join(tids[i], nullptr);
//     if (n) {
//       printf("thread %p join fail , the n is %d\n", (void *)tids[i], n);
//     }
//   }
//   sleep(2);

//   return 0;
// }

// // ##################################################

// __thread int g_val = 0; // 使用 __thread 修饰全局变量 g_val

// class threadData {
//  public:
//   threadData(const pthread_t tid) : tid_(tid) {
//     threadname_ = "Thread_" + std::to_string(tid % 1000);
//   }

//  public:
//   pthread_t tid_;
//   std::string threadname_;
// };

// void *threadRoutine(void *args) {

//   pthread_t tid = pthread_self();
//   threadData self_data(tid);
//   while (1) {
//     printf("I am %s , the tid : %p , the g_val = %d , the &g_val is %p\n",
//            self_data.threadname_.c_str(), (void *)tid, g_val,
//     //       &g_val);  // 输出线程信息 并打印出全局变量 g_val 的值与地址
//     g_val++;

//     sleep(1);
//   }
//   return nullptr;
// }

// int main() {
//   std::vector<pthread_t> tids;

//   for (size_t i = 0; i < NUM; ++i) {
//     pthread_t tid;
//     pthread_create(&tid, nullptr, threadRoutine, nullptr);
//     tids.push_back(tid);
//   }

//   for (size_t i = 0; i < tids.size(); ++i) {
//     pthread_join(tids[i], nullptr);
//   }

//   sleep(2);

//   return 0;
// }

// // ##################################################

// class threadData {
//  public:
//   threadData(const pthread_t tid) : tid_(tid) {
//     threadname_ = "Thread_" + std::to_string(tid % 1000);
//   }

//  public:
//   pthread_t tid_;
//   std::string threadname_;
// };

// void *threadRoutine(void *args) {
//   int test_num = 0; // 添加局部变量 test_num

//   pthread_t tid = pthread_self();
//   threadData self_data(tid);
//   while (1) {
//     printf("I am %s , the tid : %p , the test_num = %d , the &test_num is
//     %p\n",
//            self_data.threadname_.c_str(), (void *)tid, test_num,
//            &test_num);  // 输出线程信息
//            并打印出线程中局部变量test_num的值与地址
//     test_num++;

//     sleep(1);
//   }
//   return nullptr;
// }

// int main() {
//   std::vector<pthread_t> tids;

//   for (size_t i = 0; i < NUM; ++i) {
//     pthread_t tid;
//     pthread_create(&tid, nullptr, threadRoutine, nullptr);
//     tids.push_back(tid);
//   }

//   for (size_t i = 0; i < tids.size(); ++i) {
//     pthread_join(tids[i], nullptr);
//   }

//   sleep(2);

//   return 0;
// }

// ##################################################

// int test_num = 0;

// class threadData {
//   // 设计了一个类用来封装线程的基本信息
//  public:
//   threadData(const pthread_t tid) : tid_(tid) {
//     // 构造函数，初始化线程数据
//     // 不在主线程中调用构造函数是为了在线程内部自行对属性进行初始化
//     // 如果在主线程中直接调用构造函数进行初始化则无法正确获取其tid
//     threadname_ = "Thread_" + std::to_string(tid % 1000);  // 简短线程名
//   }

//  public:
//   pthread_t tid_;           // 线程ID
//   std::string threadname_;  // 线程名称
// };

// void *threadRoutine(void *args) {
//   pthread_t tid = pthread_self();  // 获取当前线程ID
//   threadData self_data(tid);       // 创建线程数据对象
//   while (1) {
//     test_num++;
//     printf("I am %s , the tid : %p , the test_num = %d\n",
//            self_data.threadname_.c_str(), (void *)tid,
//            test_num);  // 输出线程信息
//     sleep(1);
//   }  // 模拟线程执行
//   return nullptr;
// }

// int main() {
//   std::vector<pthread_t> tids;  // 用于管理线程的tid

//   // 创建线程
//   for (size_t i = 0; i < NUM; ++i) {
//     pthread_t tid;                                          // 线程ID
//     pthread_create(&tid, nullptr, threadRoutine, nullptr);  // 创建线程并启动
//     tids.push_back(
//         tid);  // 将线程tid存放至STL容器中，方便主线程后期对这些线程进行管理
//   }

//   // 等待所有线程完成
//   for (size_t i = 0; i < tids.size(); ++i) {
//     pthread_join(tids[i], nullptr);  // 循环调用 pthread_join 等待线程
//   }

//   sleep(2);

//   return 0;
// }

// // ##################################################
//  // 最初的
//  class threadData {
//    // 设计了一个类用来封装线程的基本信息
//   public:
//    void DataInit(const pthread_t tid) {
//      // 不使用构造函数的原因是 将在线程内部自行对属性进行初始化
//      // 如果在主线程中直接调用构造函数进行初始化则无法正确获取其tid
//      tid_ = tid;
//      threadname_ = "Thread_" + to_string(tid % 1000);  // 简短线程名
//    }

//  public:
//   pthread_t tid_;
//   string threadname_;
// };

// void *threadRoutine(void *args) {
//   threadData *td = static_cast<threadData *>(args);
//   td->DataInit(pthread_self()); // 对线程的属性类进行初始化
//   printf("I am %s , the tid : %p\n", td->threadname_.c_str(), (void
//   *)td->tid_); sleep(3); delete static_cast<threadData *>(args);  //
//   释放线程数据维护的空间 return nullptr;
// }

// int main() {
//   vector<pthread_t> tids;  // 用于管理线程的tid
//   for (size_t i = 0; i < NUM; ++i) {
//     pthread_t tid;
//     threadData *td =
//         new threadData();  //
//         在堆区创建空间确保改变量的生命周期不会在传入后因为
//                            // for 循环的结束而结束
//     pthread_create(&tid, nullptr, threadRoutine, td);  // 创建线程

//     tids.push_back(
//         tid);  // 将线程tid存放至STL容器中方便主线程后期对这些线程进行管理
//   }

//   for (size_t i = 0; i < tids.size(); ++i) {
//     // 循环调用 pthread_join 等待线程
//     pthread_join(tids[i], nullptr);
//   }

//   return 0;
// }

//////////////////////////////////////////////

// class threadData {
//   // 设计了一个类用来封装线程的基本信息
//  public:
//   threadData(const pthread_t tid) : tid_(tid) {
//     // 构造函数，初始化线程数据
//     // 不在主线程中调用构造函数是为了在线程内部自行对属性进行初始化
//     // 如果在主线程中直接调用构造函数进行初始化则无法正确获取其tid
//     threadname_ = "Thread_" + std::to_string(tid % 1000);  // 简短线程名
//   }

//  public:
//   pthread_t tid_;           // 线程ID
//   std::string threadname_;  // 线程名称
// };

// void *threadRoutine(void *args) {
//   pthread_t tid = pthread_self();  // 获取当前线程ID
//   threadData self_data(tid);       // 创建线程数据对象
//   printf("I am %s , the tid : %p\n", self_data.threadname_.c_str(),
//          (void *)tid);  // 输出线程信息
//   sleep(2);             // 模拟线程执行
//   return nullptr;
// }

// int main() {
//   std::vector<pthread_t> tids;  // 用于管理线程的tid

//   // 创建线程
//   for (size_t i = 0; i < NUM; ++i) {
//     pthread_t tid;                                          // 线程ID
//     pthread_create(&tid, nullptr, threadRoutine, nullptr);  // 创建线程并启动
//     tids.push_back(
//         tid);  // 将线程tid存放至STL容器中，方便主线程后期对这些线程进行管理
//   }

//   // 等待所有线程完成
//   for (size_t i = 0; i < tids.size(); ++i) {
//     pthread_join(tids[i], nullptr);  // 循环调用 pthread_join 等待线程
//   }

//   sleep(2);

//   return 0;
// }
